package world_manager

import (
	"github.com/golang/protobuf/proto"
	"go_server/game_server/event_manager"
	"go_server/game_server/event_manager/event_data/event_impl"
	"go_server/game_server/protocol/pb"
	"go_server/zinx/zconstant"
	"go_server/zinx/ziface"
	"go_server/zinx/zutils"
)

type worldManager struct {
	playerMaps *zutils.ConcurrentHashMap[int64]
}

var WorldMgrObj *worldManager

func init() {
	WorldMgrObj = &worldManager{
		playerMaps: zutils.NewConcurrentHashMap[int64](zconstant.CONCURRENT_SEG, zconstant.CONCURRENT_TOTAL),
	}
}

func (wm *worldManager) AddPlayerConn(roleId int64, conn ziface.IConnection) {
	wm.playerMaps.Set(roleId, conn)
}

func (wm *worldManager) RemovePlayerConn(roleId int64)  {
	wm.playerMaps.Remove(roleId)
}

func (wm *worldManager) GetPlayerConn(roleId int64) ziface.IConnection{
	conn, exist := wm.playerMaps.Get(roleId)
	if !exist {
		return nil
	}
	return conn.(ziface.IConnection)
}

func (wm *worldManager) GetOnlinePlayersConn() []ziface.IConnection {
	playersConn := make([]ziface.IConnection, 0)
	values := wm.playerMaps.GetAllValues()
	for index := range values {
		playersConn = append(playersConn, values[index].(ziface.IConnection))
	}
	return playersConn
}

func (wm *worldManager) SendServerShutdownEvent() {
	connArr := wm.GetOnlinePlayersConn()
	onlineCount := len(connArr)
	eventServerCount := event_manager.EventManagerObj.GetServerShutdownEventCount()
	event_manager.EventManagerObj.Wg.Add(eventServerCount * onlineCount)

	for _, conn := range connArr {
		roleId, err := conn.GetProperty("roleId")
		if  err != nil {
			continue
		}

		nRoleId := roleId.(int64)
		if nRoleId <= 0 {
			continue
		}
		serverShutdownEvent := event_impl.NewRoleLogoutEvent(nRoleId, conn, &event_manager.EventManagerObj.Wg)
		event_manager.EventManagerObj.FireEventData(serverShutdownEvent)
	}
	wm.playerMaps.Clear()
}

func (wm *worldManager) RemoveRoleLogoutCallBack() {
	connArr := wm.GetOnlinePlayersConn()
	for _, conn := range connArr {
		conn.RemoveOnConnStop()
	}
}

func (wm *worldManager) PushClientMsg(roleId int64, msgId pb.ProtocolManager, msgData proto.Message) {
	playerConn := wm.GetPlayerConn(roleId)
	if playerConn == nil {
		return
	}
	playerConn.SendBuffPBMsg(uint32(msgId), msgData)
}

func (wm *worldManager) SendClientErrMsg(roleId int64, request ziface.IRequest, errCode pb.ErrorCodeManager, param []string) {
	msg := &pb.ErrorCodeS2C{
		Cmd: int32(request.GetMsgID()),
		Code: errCode,
		Params: param,
	}

	wm.PushClientMsg(roleId, pb.ProtocolManager_ErrorCode, msg)
}

